home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / ui / wais-ui.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  24KB  |  947 lines

  1. /* 
  2.   WIDE AREA INFORMATION SERVER SOFTWARE:
  3.    No guarantees or restrictions.  See the readme file for the full standard
  4.    disclaimer.
  5.  
  6.    This is part of the shell user-interface tools for the WAIS software.
  7.    Do with it as you please.
  8.  
  9.    jonathan@Think.COM
  10.  *
  11.  * $Log:    wais-ui.c,v $
  12.  * Revision 1.22  92/05/07  14:52:04  jonathan
  13.  * Changed use of setitimer to alarm.  Thanks to
  14.  * steinkel@carlisle-emh2.army.mil.
  15.  * 
  16.  * Revision 1.21  92/04/30  10:59:05  jonathan
  17.  * Replace strdup with s_strdup.
  18.  * 
  19.  * Revision 1.20  92/04/02  14:21:59  jonathan
  20.  * Copy type in all calls to makeDocObjUsing a generate_retrieval_apdu (which
  21.  * calls makeDocObjUsing...).
  22.  * 
  23.  * Revision 1.19  92/04/01  17:19:35  jonathan
  24.  * Fixed reporting of diagnostics when return text is empty.
  25.  * 
  26.  * Revision 1.18  92/03/17  14:33:17  jonathan
  27.  * Renamed to wais-ui, cleaned up for use by X interface as well as shell
  28.  * interfaces.
  29.  * 
  30.  * Revision 1.17  92/03/08  10:42:28  jonathan
  31.  * Added one last loadSource in ViewWaisDocument.
  32.  * 
  33.  * Revision 1.16  92/03/06  14:50:13  jonathan
  34.  * New and Improved source loading!
  35.  * 
  36.  */
  37.  
  38. #ifndef lint
  39. static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ui/RCS/wais-ui.c,v 1.22 92/05/07 14:52:04 jonathan Exp $";
  40. #endif
  41.  
  42. #define _C_QUESTION
  43.  
  44. #include "wais.h"
  45. #include "globals.h"
  46.  
  47. void showDiags(d)
  48. diagnosticRecord **d;
  49. {
  50.   int i;
  51.   char msg[256];
  52.  
  53.   for (i = 0; d[i] != NULL; i++) {
  54.     if (d[i]->ADDINFO != NULL) {
  55.       sprintf(msg, "\nCode: %s, %s", d[i]->DIAG, d[i] ->ADDINFO);
  56.       PrintStatus(msg);
  57.       sleep(2);
  58.     }
  59.   }
  60. }
  61.       
  62. void printDiags(d)
  63. diagnosticRecord **d;
  64. {
  65.   int i;
  66.  
  67.   for (i = 0; d[i] != NULL; i++)
  68.     if (d[i]->ADDINFO != NULL)
  69.       printf("%s\n", d[i] ->ADDINFO);
  70. }
  71.       
  72. void
  73. write_text_record_completely(fp, record, quote_string_quotes)
  74. FILE *fp;
  75. WAISDocumentText *record;
  76. Boolean quote_string_quotes;
  77. {
  78.   long count;
  79.   /* fprintf(fp," Text\n");
  80.   print_any("     DocumentID:  ", record->DocumentID);
  81.   fprintf(fp,"     VersionNumber:  %d\n", record->VersionNumber);
  82.   */
  83.   for(count = 0; count < record->DocumentText->size; count++){
  84.     int ch = record->DocumentText->bytes[count];
  85.     if(27 == ch){
  86.       /* then we have an escape code */
  87.       /* if the next letter is '(' or ')', then ignore two letters */
  88.       if('(' == record->DocumentText->bytes[count + 1] ||
  89.       ')' == record->DocumentText->bytes[count + 1])
  90.     count += 1;             /* it is a term marker */
  91.       else count += 4;         /* it is a paragraph marker */
  92.     }
  93.     else if (isprint(ch)){
  94.       if(quote_string_quotes && ch == '"')
  95.     putc('\\', fp);
  96.       putc(ch, fp);
  97.     } 
  98.     else if (ch == '\n' || ch == '\r')
  99.       fprintf(fp, "\n");
  100.   }
  101. }
  102.  
  103.  
  104. /* for making searches */
  105.  
  106. DocList
  107. build_response_list(response, source)
  108. SearchResponseAPDU *response;
  109. SourceID source;
  110. {
  111.   long i, k;
  112.   WAISSearchResponse  *info;
  113.   DocList last = NULL, doc, result = NULL;
  114.   DocumentID docID;
  115.  
  116.   k = response->NumberOfRecordsReturned;
  117.  
  118.   if ( response->DatabaseDiagnosticRecords != 0 ) {
  119.     info = (WAISSearchResponse*)response->DatabaseDiagnosticRecords;
  120.     if ( info->DocHeaders != NULL ) {
  121.       for(i = 0; i < k; i++) {
  122.     if(info->DocHeaders[i] != NULL ) {
  123.       if(result == NULL) {
  124.         doc = result = makeDocList(NULL, NULL);
  125.       }
  126.       else
  127.         doc = makeDocList(NULL, NULL);
  128.  
  129.       docID = fillDocumentID(info->DocHeaders[i], source);
  130.       doc->thisDoc = docID;
  131.  
  132.       if(last != NULL) {
  133.         last->nextDoc = doc;
  134.       }
  135.       last = doc;
  136.     }
  137.       }
  138.     }
  139.   }
  140.   return result;
  141. }
  142.  
  143. /* right now this hacks out the ^Q/S too.  I'll do better later. */
  144.  
  145. static void
  146.  replacecontrolM(buffer, length)
  147. char *buffer;
  148. long *length;
  149. {
  150.   char *here, *there, c;
  151.   long i, newlength;
  152.  
  153.   here = there = buffer;
  154.   for(newlength = 0, i = 0; i < *length; i++) {
  155.     c = *here;
  156.     switch (c) {
  157.     case 0:
  158.       *there = 0;
  159.       *length = newlength;
  160.       return;
  161.     case '\r':
  162.       *there = '\n';
  163.       newlength++;
  164.       here++; there++;
  165.       break;
  166.     case 19:
  167.     case 17:
  168.       here++;
  169.       break;
  170.     default:
  171.       *there = *here;
  172.       newlength++;
  173.       here++; there++;
  174.     }
  175.   }
  176.   *length = newlength;
  177. }
  178.  
  179. void SearchWais(q)
  180. Question q;
  181. {
  182.   Source source;
  183.   SList asource;
  184.   static long request_buffer_length;
  185.   DocObj **Doc;
  186.   int i;
  187.   char *request_message, *response_message;
  188.   char message[255];
  189.   DocList last;
  190.   diagnosticRecord **diag;
  191.   char *database;
  192.   long numdocs, result;
  193.  
  194.   request_message = (char*)q->request_message;
  195.   response_message = (char*)q->response_message;
  196.  
  197.   /* clear the results */
  198.  
  199.   /*
  200.   freeDocList(q->ResultDocuments);
  201.   */
  202.   q->ResultDocuments = NULL;
  203.  
  204.   /* build DocObjs */
  205.  
  206.   Doc = (DocObj**)s_malloc((q->numdocs+1) * sizeof(char*));
  207.   
  208.   q->numsources = listlength((List)q->Sources);
  209.  
  210.   if (q->numsources != 0)
  211.     numdocs = maxDocs/q->numsources;
  212.   else numdocs = 0;
  213.   {
  214.     DocList dl;
  215.     for(i=0, dl = q->RelevantDocuments;
  216.     dl != NULL;
  217.     dl = dl->nextDoc, i++)
  218.       if(dl->thisDoc->doc != NULL) {
  219.     char* tmptype = s_strdup((dl->thisDoc->doc->type) ?
  220.                  dl->thisDoc->doc->type[0] : "TEXT");
  221.  
  222.     if(dl->thisDoc->doc->id != NULL)
  223.       if(dl->thisDoc->start >= 0)
  224.           
  225.         Doc[i] =
  226.           makeDocObjUsingLines(anyFromDocID(dl->thisDoc->doc->id),
  227.                    tmptype, dl->thisDoc->start, dl->thisDoc->end);
  228.       else
  229.         Doc[i] =
  230.           makeDocObjUsingWholeDocument(anyFromDocID(dl->thisDoc->doc->id),
  231.                        tmptype);
  232.  
  233.       }
  234.     Doc[i] = NULL;
  235.   }
  236.  
  237.   /* check to see if the question has a source */
  238.   source = NULL;
  239.  
  240.   if(q->Sources != NULL) {
  241.     SourceList slist;
  242.  
  243.     for(slist = q->Sources;
  244.     slist != NULL;
  245.     slist = slist->nextSource) {
  246.       source = findsource(slist->thisSource->filename);
  247.  
  248.       if (source == NULL) {
  249.     sprintf(message, "\nCouldn't find source: %s.", slist->thisSource->filename);
  250.     PrintStatus(message);
  251.     sleep(2);
  252.       }
  253.       else {
  254.         if (strstr(source->name,".src")!=NULL) {
  255.       sprintf(message, "\nSearching: ");
  256.       strncat(message,source->name,strlen(source->name)-4);
  257.         }
  258.         else
  259.       sprintf(message, "\nSearching: %s", source->name);
  260.     
  261.     PrintStatus(message);
  262.       
  263.     if(source->initp != TRUE) {
  264.       PrintStatus("\nInitializing connection...");
  265.       init_for_source(source, request_message, MAX_MESSAGE_LEN, 
  266.               response_message);
  267.       PrintStatus(message);
  268.     }
  269.     if(source->database[0] == 0) database = NULL;
  270.     else database = source->database;
  271.  
  272.     if(source->initp != FALSE) {
  273.       result = 0;
  274.       request_buffer_length = source->buffer_length;
  275.       if(NULL ==
  276.          generate_search_apdu(request_message + HEADER_LENGTH, 
  277.                   &request_buffer_length, 
  278.                   q->keywords, database, Doc, numdocs)) {
  279.         PrintStatus("Buffer overflow: request too large");
  280.         sleep(2);
  281.       }
  282.       else if((result =
  283.            interpret_message(request_message, 
  284.                      (source->buffer_length - 
  285.                       request_buffer_length), 
  286.                      response_message,
  287.                      source->buffer_length,
  288.                      source->connection,
  289.                      false /* true verbose */
  290.                      )) == 0) {
  291.         PrintStatus("Warning: no information returned.  Possibly a bad connection");
  292.         close_source(source);
  293.       }
  294.       if (result != 0) { /* use the repsonse */
  295.         readSearchResponseAPDU(&q->query_response,
  296.                    response_message + HEADER_LENGTH);
  297.  
  298.       
  299.         if (q->query_response != NULL)
  300.           if ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords != NULL) 
  301.         if ((diag =
  302.              ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
  303.           showDiags(diag);
  304.       
  305.         if (q->ResultDocuments != NULL) {
  306.           last = findLast(q->ResultDocuments);
  307.           last->nextDoc = build_response_list(q->query_response,
  308.                           slist->thisSource);
  309.         }
  310.         else
  311.           q->ResultDocuments =
  312.         build_response_list(q->query_response,
  313.                     slist->thisSource);
  314.       }
  315.     }
  316.     else {
  317.       sprintf(message, "\nError connecting to %s", source->name);
  318.       PrintStatus(message);
  319.       sleep(2);
  320.     }
  321.       }
  322.     }
  323.     /* ok, now we've got all the documents, let's sort them */
  324.  
  325.     sort_document_list(q->ResultDocuments);
  326.  
  327.     q->numresdocs =  listlength((List)q->ResultDocuments);
  328.     sprintf(message, "\nFound %d items.", q->numresdocs);
  329.     PrintStatus(message);
  330.   }
  331.   else {
  332.     PrintStatus("\nThis Question has no sources to search.  Please add one.");
  333.     q->ResultDocuments = NULL;
  334.     q->numresdocs =  listlength((List)q->ResultDocuments);
  335.   }
  336.   if (Doc != NULL) {
  337.     doList((void**)Doc,freeDocObj);
  338.     s_free(Doc);
  339.   }
  340. }
  341.  
  342. char* GetWaisDocument(q, doc, type, fp, written)
  343. Question q;
  344. DocumentID doc;
  345. char *type;
  346. FILE *fp;
  347. long* written;
  348. {
  349.   static long request_length, chars_per_page;
  350.   static long lines, size, count, chars, numChars;
  351.   long start_byte, end_byte;
  352.   any* docany;
  353.   WAISDocumentText *text;
  354.   diagnosticRecord **diag;
  355.   char *viewtext, message[255];
  356.   char *viewbuffer;
  357.   char *tmptype;
  358.   Source source;
  359.   SList asource;
  360.   char *database;
  361.   long result;
  362.  
  363.   sprintf(message, "\nGetting document from server...");
  364.   if(fp != stdout)
  365.     PrintStatus(message);
  366.  
  367.   source = NULL;
  368.  
  369.   if(doc == NULL) return NULL;
  370.  
  371.   if(doc->doc != NULL &&
  372.      doc->doc->sourceID != NULL &&
  373.      doc->doc->sourceID->filename != NULL) {
  374.     source = findsource(doc->doc->sourceID->filename);
  375.   }
  376.  
  377.   if (source == NULL) {
  378.  
  379.     PrintStatus("\nCould not find Source for this document!");
  380.     return NULL;
  381.   }
  382.  
  383.   if(source->database[0] == 0) database = NULL;
  384.   else database = source->database;
  385.  
  386.   size = 0;
  387.  
  388.   lines = doc->doc->numLines;
  389.   if(written != NULL && *written != 0)
  390.     chars = *written;
  391.   else
  392.     chars = doc->doc->numChars;
  393.  
  394.   numChars = chars+1000;    /* for slop? */
  395.  
  396.   docany = anyFromDocID(doc->doc->id);
  397.  
  398.   if(source->initp == FALSE)
  399.     init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
  400.             q->response_message);
  401.  
  402.  
  403.   if(source->initp == FALSE) {
  404.     PrintStatus("\nInit Connection Failed.");
  405.     *written = 0;
  406.     return(NULL);
  407.   }
  408.  
  409.   chars_per_page = source->buffer_length - HEADER_LENGTH - 1000; /* ? */
  410.  
  411.   if(fp == NULL) {
  412.     viewbuffer = (char*)s_malloc(chars < 0 ? chars_per_page : numChars);
  413.  
  414.     if(viewbuffer == NULL) {
  415.       PrintStatus("\nUnable to allocate message space.  Something is wrong.");
  416.       return NULL;
  417.     }
  418.     viewtext = viewbuffer;
  419.   }
  420.  
  421.   tmptype = s_strdup((type ? type : "TEXT"));
  422.  
  423.   if (chars == 0)
  424.     PrintStatus("\nEmpty document!");
  425.   else if (source->initp != FALSE) {
  426.     for(count = 0; 
  427.     (chars < 0) || (count * chars_per_page < chars);
  428.     count++) {
  429.       /* show as we go... */
  430.       request_length = source->buffer_length;
  431.  
  432.       if (chars < 0) {
  433.     numChars = (count+1) * chars_per_page;
  434.     if(fp == NULL) {
  435.       viewbuffer = s_realloc(viewbuffer, numChars);
  436.     }
  437.       }
  438.  
  439.       start_byte = count * chars_per_page;
  440.       end_byte = (chars < 0 ? 
  441.           (count + 1) * chars_per_page :
  442.           MIN((count + 1) * chars_per_page, chars));
  443.       if(NULL ==
  444.      generate_retrieval_apdu(q->request_message + HEADER_LENGTH,
  445.                  &request_length, docany, CT_byte,
  446.                  start_byte, end_byte,
  447.                  tmptype, database)) {
  448.     PrintStatus("\nWarning: buffer overflow.");
  449.     return NULL;
  450.       }
  451.          
  452.       if((result =
  453.       interpret_message(q->request_message, 
  454.                 source->buffer_length - request_length, 
  455.                 q->response_message,
  456.                 source->buffer_length,
  457.                 source->connection,
  458.                 false /* true verbose */    
  459.                 )) == 0) {
  460.     PrintStatus("\nWarning: no information returned.  Possibly a bad connection.");
  461.     close_source(source);
  462.     return NULL;
  463.       }
  464.       if (result != 0) 
  465.     readSearchResponseAPDU(&q->retrieval_response, 
  466.                    q->response_message + HEADER_LENGTH);
  467.  
  468.       if (q->retrieval_response != NULL)  {
  469.     if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL) {
  470.       diag = ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics;
  471.     }
  472.     else diag = NULL;
  473.       
  474.     if(NULL == ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text) {
  475.       if (diag != NULL)
  476.         showDiags(diag);
  477.     
  478.       PrintStatus("done.");
  479.       if(written != NULL) *written = size;
  480.       return(viewbuffer);
  481.     }
  482.     else {
  483.       text = ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text[0];
  484.       if((type == NULL) || (strcmp(type, "TEXT") == 0)) {
  485.         long length = text->DocumentText->size;;
  486.         
  487.         delete_seeker_codes(text->DocumentText->bytes, &length);
  488.         text->DocumentText->size = length;
  489.         replacecontrolM(text->DocumentText->bytes, &length);
  490.         text->DocumentText->size = length;
  491.       }
  492.  
  493.       if(text->DocumentText->size > (end_byte - start_byte))
  494.         /* something wrong! */
  495.         text->DocumentText->size = (end_byte - start_byte);
  496.  
  497.       viewtext = viewbuffer+size;
  498.       size+=text->DocumentText->size;
  499.       if (size <= numChars) {
  500.         if(fp == NULL) {
  501.           memcpy(viewtext, text->DocumentText->bytes, text->DocumentText->size);
  502.         }
  503.         else {
  504.           dumptext(fp, text->DocumentText->bytes, text->DocumentText->size);
  505.         }
  506.  
  507.         sprintf(message, "\nReceived %d bytes from %s...",
  508.             size, source->server);
  509.  
  510.         if(fp != stdout)
  511.           PrintStatus(message);
  512.  
  513.         if(diag &&
  514.            diag[0] &&
  515.            diag[0]->ADDINFO != NULL &&
  516.            !strcmp(diag[0]->DIAG, D_PresentRequestOutOfRange))
  517.           break;
  518.         if((type != NULL) &&
  519.            (strcmp(type, "TEXT") != 0) &&
  520.            (text->DocumentText->size != chars_per_page))
  521.           break;
  522.       }
  523.       else {
  524.         PrintStatus("\nBuffer overflow!");
  525.         break;
  526.       }
  527.     }
  528.  
  529.     if (diag != NULL)
  530.       showDiags(diag);
  531.     
  532.       }
  533.     }
  534.   }
  535.   if (written != NULL) *written = size;
  536.   return(viewbuffer);
  537. }
  538.  
  539. void RetrieveWaisDocument(start_output, end_output, q, doc)
  540. void (*start_output)();
  541. void (*end_output)();
  542. Question q;
  543. DocumentID doc;
  544. {
  545.   static long request_length, chars_per_page;
  546.   static long lines, size, count, chars, numChars;
  547.   any* docany;
  548.   WAISDocumentText *text;
  549.   diagnosticRecord **diag;
  550.   char *viewtext;
  551.   char *viewbuffer;
  552.   Source source;
  553.   SList asource;
  554.   char *database;
  555.   FILE *fp;
  556.   int output_started;
  557.  
  558.   output_started = FALSE;
  559.   source = NULL;
  560.  
  561.   if(doc->doc != NULL) {
  562.     if(doc->doc->sourceID != NULL) {
  563.       if(doc->doc->sourceID->filename != NULL) {
  564.  
  565.     char *sourcename;
  566.     sourcename = doc->doc->sourceID->filename;
  567.  
  568.     for(asource = Sources;
  569.         asource != NULL;
  570.         asource = asource->nextSource) {
  571.       if (!strcmp(sourcename, asource->thisSource->name)) {
  572.         source = asource->thisSource;
  573.         break;
  574.       }
  575.     }
  576.       }
  577.     }
  578.   }
  579.  
  580.   if (source == NULL) {
  581.     PrintStatus("Could not find Source for this document!");
  582.     return;
  583.   }
  584.  
  585.   if(source->database[0] == 0) database = NULL;
  586.   else database = source->database;
  587.  
  588.   size = 0;
  589.  
  590.   lines = doc->doc->numLines;
  591.   chars = doc->doc->numChars;
  592.   numChars = chars + 1000; /* for slop? */
  593.  
  594.   if((viewbuffer = (char*)s_malloc(numChars)) == NULL) {
  595.     PrintStatus("\nUnable to allocate message space.  Something is wrong.");
  596.     return;
  597.   }
  598.  
  599.   viewtext = viewbuffer;
  600.  
  601.   docany = anyFromDocID(doc->doc->id);
  602.  
  603.   if(source->initp == FALSE)
  604.     init_for_source(source, q->request_message,  MAX_MESSAGE_LEN,
  605.             q->response_message);
  606.  
  607.   chars_per_page = source->buffer_length - HEADER_LENGTH - 1000; /* ? */
  608.  
  609.   if (chars <= 0)
  610.       PrintStatus("\nEmpty document.");
  611.   else if (source->initp != FALSE) {
  612.     for(count = 0; 
  613.     count * chars_per_page < chars;
  614.     count++) {
  615.       /* show as we go... */
  616.  
  617.       request_length = source->buffer_length;
  618.  
  619.       if(0 ==
  620.      generate_retrieval_apdu(q->request_message + HEADER_LENGTH,
  621.                  &request_length, 
  622.                  docany,
  623.                  CT_byte,
  624.                  count * chars_per_page,
  625.                  MIN((count + 1) * chars_per_page, chars),
  626.                  (doc->doc->type) ?
  627.                  doc->doc->type[0] : "TEXT",
  628.                  database)) {
  629.     PrintStatus("\nWarning: no information returned.  Possibly a bad connection.");
  630.     break;
  631.       }
  632.          
  633.       if(0 ==
  634.      interpret_message(q->request_message, 
  635.                source->buffer_length - request_length, 
  636.                q->response_message,
  637.                source->buffer_length,
  638.                source->connection,
  639.                false /* true verbose */    
  640.                )) {
  641.     PrintStatus("\nWarning: no information returned.  Possibly a bad connection.");
  642.     break;
  643.       }
  644.  
  645.       readSearchResponseAPDU(&q->retrieval_response, 
  646.                  q->response_message + HEADER_LENGTH);
  647.  
  648.       if (q->retrieval_response != NULL)
  649.     if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL) 
  650.       if ((diag =
  651.            ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
  652.         showDiags(diag);
  653.     
  654.       if(NULL == ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text) {
  655.     break;
  656.       }
  657.  
  658.       text = ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text[0];
  659.       {
  660.     long length;
  661.     
  662.     length = text->DocumentText->size;
  663.     if((doc->doc->type == NULL) || (strcmp(doc->doc->type, "TEXT") == 0)) {
  664.       delete_seeker_codes(text->DocumentText->bytes, &length);
  665.       text->DocumentText->size = length;
  666.       replacecontrolM(text->DocumentText->bytes, &length);
  667.       text->DocumentText->size = length;
  668.     }
  669.       }
  670.  
  671.       size+=text->DocumentText->size;
  672.       if (size <= numChars) {
  673.     memcpy(viewtext, text->DocumentText->bytes, text->DocumentText->size);
  674.     viewtext+=text->DocumentText->size;
  675.       }
  676.       else {
  677.     PrintStatus("\nBuffer overflow!");
  678.     break;
  679.       }
  680.  
  681.     }
  682.  
  683.     /* display_search_response(q->retrieval_response); the general thing */
  684.     if(NULL == ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text){
  685.       PrintStatus("\nNo text was returned.");
  686.     } else {
  687.       if (output_started==FALSE) {
  688.          start_output(&fp);
  689.          output_started=TRUE;
  690.          if (&fp==NULL) {
  691.            PrintStatus("Unable to open output.");
  692.        return;
  693.     }
  694.       }
  695.       dumptext(fp, viewbuffer, size);
  696.     }
  697.   }
  698.   if (output_started==TRUE) 
  699.     end_output(&fp);
  700. }
  701.  
  702. void dumptext(fp, buffer, size)
  703. FILE *fp;
  704. char *buffer;
  705. long size;
  706. {
  707.   long i;
  708.  
  709.   for (i = 0; i < size; i++)
  710.       fputc(*buffer++,fp);
  711.   fflush(fp);
  712. }
  713.   
  714. #include <signal.h>
  715. #include <setjmp.h>
  716. static jmp_buf jbuf;
  717. static int new, old;
  718.  
  719. static void
  720. alarmhandler(sig, code, scp, addr)
  721. long sig, code;
  722. struct sigcontext *scp;
  723. char *addr;
  724. {
  725.   longjmp(jbuf, 1);
  726. }
  727.  
  728. void test_connection(q)
  729. Question q;
  730. {
  731.   Source source;
  732.   SList asource;
  733.   static long request_buffer_length;
  734.   char *request_message, *response_message;
  735.   char message[255];
  736.   diagnosticRecord **diag;
  737.   char *database;
  738.  
  739.   new = 120; /* 2 minute timeout. */
  740.  
  741.   request_message = (char*)q->request_message;
  742.   response_message = (char*)q->response_message;
  743.  
  744.   /* check to see if the question has a source */
  745.   source = NULL;
  746.  
  747.   if(q->Sources != NULL) {
  748.     SourceList slist;
  749.  
  750.     for(slist = q->Sources;
  751.     slist != NULL;
  752.     slist = slist->nextSource) {
  753.       for(asource = Sources;
  754.       asource != NULL;
  755.       asource = asource->nextSource) {
  756.     if (asource->thisSource != NULL &&
  757.         asource->thisSource->name != NULL &&
  758.         !strcmp(slist->thisSource->filename,
  759.             asource->thisSource->name)) {
  760.       source = asource->thisSource;
  761.       break;
  762.     }
  763.       }
  764.  
  765.       if (source == NULL) {
  766.     sprintf(message, "\nCouldn't find source: %s.", slist->thisSource->filename);
  767.     PrintStatus(message);
  768.       }
  769.       else {
  770.     printf("Source %s ", slist->thisSource->filename);
  771.     if(source->maintainer) 
  772.       printf("by %s ", source->maintainer);
  773.     if(source->server[0] != 0)
  774.       printf("at %s ", source->server);
  775.  
  776.     if(source->initp == FALSE) {
  777.       freopen("/dev/null", "w", stderr);
  778.       if (setjmp(jbuf) != 0) {
  779.         source->initp = FALSE;
  780.       } 
  781.       else {
  782.         signal(SIGALRM, alarmhandler);
  783.         old = alarm(new);
  784.         init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
  785.                 q->response_message);
  786.         alarm(old);
  787.         signal(SIGALRM, SIG_DFL);
  788.       }
  789.       request_buffer_length = source->buffer_length;
  790.  
  791.       if(source->initp == FALSE) {
  792.         printf("not responding.\n");
  793.       }
  794.       else {        /* now lets test the database */
  795.         if(source->database[0] == 0) database = NULL;
  796.         else database = source->database;
  797.  
  798.         if(NULL ==
  799.            generate_search_apdu(request_message + HEADER_LENGTH, 
  800.                     &request_buffer_length, 
  801.                     "?", database, NULL, 1)) {
  802.           PrintStatus("Buffer overflow: request too large");
  803.         }
  804.         else {
  805.           long r = 0;
  806.           if (setjmp(jbuf) != 0) {
  807.         printf("not responding:\n");
  808.         return;
  809.           } else {
  810.         signal(SIGALRM, alarmhandler);
  811.         old = alarm(new);
  812.         if(0 == 
  813.            (r = interpret_message(request_message, 
  814.                       (source->buffer_length - 
  815.                        request_buffer_length), 
  816.                       response_message,
  817.                       source->buffer_length,
  818.                       source->connection,
  819.                       false /* true verbose */
  820.                       ))) {
  821.           PrintStatus("Warning: no information returned.  Possibly a bad connection");
  822.         }
  823.           }
  824.           if(r != 0) {
  825.         readSearchResponseAPDU(&q->query_response,
  826.                        response_message + HEADER_LENGTH);
  827.  
  828.       
  829.         if (q->query_response != NULL)
  830.           if ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords != NULL) 
  831.             if ((diag =
  832.              ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL) {
  833.               printf("not responding:\n");
  834.               printDiags(diag);
  835.             }
  836.             else 
  837.               printf("responding.\n");
  838.           }
  839.         }
  840.       }
  841.     }
  842.       }
  843.     }
  844.   }
  845.   else {
  846.     printf("\nError: No sources to search.  Please add one.\n");
  847.   }
  848. }
  849.  
  850. void close_source(source)
  851. Source source;
  852. {
  853.   SList t;
  854.  
  855.   if (source->connection != NULL) {
  856.     fclose(source->connection);
  857.   }
  858.   for(t = Sources; t != NULL; t = t->nextSource) {
  859.     if (strcmp(t->thisSource->server, source->server) == 0 &&
  860.     strcmp(t->thisSource->service, source->service) == 0) {
  861.       t->thisSource->initp = FALSE;
  862.       t->thisSource->connection = NULL;
  863.     }
  864.   }
  865. }
  866.  
  867. DocumentID
  868.  getNextorPrevDoc(q, source, doc, nextp)
  869. Question q;
  870. Source source;
  871. DocumentID doc;
  872. Boolean nextp;
  873. {
  874.   static long request_length;
  875.   static long lines, size, count, numChars;
  876.   any* docany;
  877.   char message[255];
  878.   int i;
  879.   diagnosticRecord **diag;
  880.   char *database, *type;
  881.   DocumentID result;
  882.   DocID *newdoc;
  883.   DocObj *Doc[2];
  884.   WAISSearchResponse  *info;
  885.   char *text, document_id[MAX_FILE_NAME_LEN];
  886.   char *loc1, *loc2, *loc3, newtype[100], headline[MAX_FILE_NAME_LEN];
  887.   long newsize;
  888.  
  889.   if(source->database[0] == 0) database = NULL;
  890.   else database = source->database;
  891.  
  892.   docany = anyFromDocID(doc->doc->id);
  893.  
  894.   size = 0;
  895.  
  896.   if(nextp == TRUE)
  897.     type = "WAIS_NEXT";
  898.   else
  899.     type = "WAIS_PREV";
  900.  
  901.   if(source->initp == FALSE)
  902.     init_for_source(source,q->request_message,MAX_MESSAGE_LEN,
  903.             q->response_message);
  904.  
  905.   request_length = source->buffer_length;
  906.   
  907.   Doc[0] = makeDocObjUsingWholeDocument(docany, s_strdup(type));
  908.   Doc[1] = NULL;
  909.   if(0 ==
  910.      generate_search_apdu(q->request_message + HEADER_LENGTH, 
  911.               &request_length, 
  912.               "foo", database, Doc, 1)) {
  913.     PrintStatus("\nWarning: Buffer overflow.");
  914.     return NULL;
  915.   }
  916.          
  917.   if(0 ==
  918.      interpret_message(q->request_message, 
  919.                (source->buffer_length - request_length), 
  920.                q->response_message,
  921.                source->buffer_length,
  922.                source->connection,
  923.                false    /* true verbose */    
  924.                )) {
  925.     PrintStatus("\nWarning: no information returned.  Possibly a bad connection.  Maybe try again.");
  926.     source->initp = FALSE;
  927.     return NULL;
  928.   }
  929.  
  930.   readSearchResponseAPDU(&q->retrieval_response, 
  931.              q->response_message + HEADER_LENGTH);
  932.  
  933.   if (q->retrieval_response != NULL)
  934.     if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL) 
  935.       if ((diag =
  936.        ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
  937.     showDiags(diag);
  938.  
  939.   info = (WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords;
  940.  
  941.   if (info != NULL &&
  942.       info->DocHeaders != NULL) {
  943.     return(fillDocumentID(info->DocHeaders[0], doc->doc->sourceID));
  944.   }
  945.   else return NULL;
  946. }
  947.